package grpc_pool

import (
	"fmt"
	"sync/atomic"

	"google.golang.org/grpc"
)

// Conn 定义单个 gRPC 连接的核心操作
type Conn interface {
	// Value 返回实际的 gRPC 连接（*grpc.ClientConn）
	Value() *grpc.ClientConn
	// Close 减少连接引用计数，非临时连接归还到池，临时连接直接关闭
	Close() error
	// IsHealthy 检查连接是否健康（可正常使用）
	IsHealthy() bool
}

// conn 是 gRPC 连接的包装实现，关联连接池与状态
type conn struct {
	cc          *grpc.ClientConn // 实际的 gRPC 客户端连接
	pool        *pool            // 所属的连接池
	once        bool             // 是否为临时连接（使用后不归还池）
	streamCount uint32           // 原子变量：当前使用的 HTTP/2 流数
	closed      uint32           // 原子变量：连接是否已关闭（0=未关闭，1=已关闭）
}

// Value 实现 Conn 接口，返回实际 gRPC 连接
func (c *conn) Value() *grpc.ClientConn {
	return c.cc
}

// Close 实现 Conn 接口，处理连接归还或关闭
func (c *conn) Close() error {
	// 临时连接：直接关闭并标记
	if c.once {
		atomic.StoreUint32(&c.closed, 1)
		return c.reset()
	}

	// 非临时连接：减少流计数，归还到池
	atomic.AddUint32(&c.streamCount, ^uint32(0)) // streamCount -= 1
	c.pool.decrRef()
	return nil
}

// IsHealthy 检查连接是否健康（未关闭 + gRPC 连接状态正常）
func (c *conn) IsHealthy() bool {
	// 1. 检查连接是否已标记关闭
	if atomic.LoadUint32(&c.closed) == 1 {
		return false
	}
	fmt.Printf("%v", c.cc.GetState())
	// 2. 检查 gRPC 连接状态（StateReady 表示可正常使用）
	if c.cc == nil {
		return false
	}
	return true
}

// reset 关闭并重置连接（释放资源）
func (c *conn) reset() error {
	cc := c.cc
	c.cc = nil
	atomic.StoreUint32(&c.closed, 1)
	atomic.StoreUint32(&c.streamCount, 0)

	if cc != nil {
		return cc.Close()
	}
	return nil
}

// wrapConn 创建 conn 实例，包装 gRPC 连接
func (p *pool) wrapConn(cc *grpc.ClientConn, once bool) *conn {
	return &conn{
		cc:          cc,
		pool:        p,
		once:        once,
		streamCount: 0,
		closed:      0,
	}
}
